package com.px.plan.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.px.common.annotation.DataScope;
import com.px.common.config.RuoYiConfig;
import com.px.common.constant.CacheConstants;
import com.px.common.constant.VideoConstant;
import com.px.common.core.redis.RedisCache;
import com.px.common.exception.ServiceException;
import com.px.common.utils.DateUtils;
import com.px.common.utils.MinioUtil;
import com.px.common.utils.Threads;
import com.px.common.utils.uuid.Seq;
import com.px.framework.mqtt.MqttServiceServiceImpl;
import com.px.plan.domain.*;
import com.px.plan.mapper.PlanActionMapper;
import com.px.plan.mapper.PlanActionRecordMapper;
import com.px.plan.service.IPlanActionSchemeService;
import com.px.plan.service.IPlanActionService;
import com.px.plan.service.IPlanActionUserService;
import com.px.plan.domain.PlanActionRecordMedia;
import com.px.system.domain.vo.PushMqVo;
import com.px.plan.mapper.PlanActionRecordMediaMapper;
import com.px.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.px.framework.mqtt.model.TopicConst.*;

/**
 * 飞行行动Service业务层处理
 *
 * @author WRJ
 * @date 2024-08
 */
@Service
public class PlanActionServiceImpl implements IPlanActionService {
    @Autowired
    private PlanActionMapper planActionMapper;
    @Autowired
    private IPlanActionSchemeService planActionSchemeService;
    @Autowired
    private MqttServiceServiceImpl MqttService;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private IPlanActionUserService planActionUserService;
    @Autowired
    private PlanActionRecordMapper planActionRecordMapper;
    @Autowired
    private PlanActionRecordMediaMapper planActionRecordMediaMapper;

    @Autowired
    private RedisCache redisCache;

    @Value("${mediaServer.sendUrl}")
    private String sendUrl;

    @Value("${mediaServer.url}")
    private String url;

    @Value("${mediaServer.secret}")
    private String secret;

    @Value("${mediaServer.customizedPath}")
    private String customizedPath;

    @Value("${minio.bucketName}")
    private String bucketName;

    @Value("${minio.endpoint}")
    private String endpoint;

    /**
     * 查询飞行行动
     *
     * @param id 飞行行动主键
     * @return 飞行行动
     */
    @Override
    public PlanAction selectPlanActionById(Long id) {
        return planActionMapper.selectPlanActionById(id);
    }

    /**
     * 查询飞行行动列表
     *
     * @param planAction 飞行行动
     * @return 飞行行动
     */
    @Override
    @DataScope(deptAlias = "pa")
    public List<PlanAction> selectPlanActionList(PlanAction planAction) {
        return planActionMapper.selectPlanActionList(planAction);
    }

    /**
     * 新增飞行行动
     *
     * @param planAction 飞行行动
     * @return 结果
     */
    @Override
    public int insertPlanAction(PlanAction planAction) {


        planAction.setPilotId(planAction.getActionUsers().stream().map(u -> u.getUserId() + "").collect(Collectors.joining(",")));
        planAction.setPilotName(planAction.getActionUsers().stream().map(PlanActionUser::getNickName).collect(Collectors.joining(",")));
        int i = planActionMapper.insertPlanAction(planAction);

        // 同步新增到行动用户表
        if (CollectionUtil.isNotEmpty(planAction.getActionUsers())) {
            planAction.getActionUsers().forEach(u -> {
                u.setActionId(planAction.getId());
                planActionUserService.insertPlanActionUser(u);
            });
        }
        List<String> pilotIdList = Arrays.asList(planAction.getPilotId().split(","));
        //根据飞手Id查询设备sn码
        List<String> droneList = userMapper.selectUserByIds(pilotIdList);
        redisCache.setCacheList(CacheConstants.PLAN_ACTION_USERNAME + planAction.getId(), droneList);
        //发送mq
        droneList.stream().forEach(drone -> {
            PushMqVo pushMqVo = new PushMqVo();
            pushMqVo.setSn("");
            pushMqVo.setUserName(drone);
            pushMqVo.setType(PLAN_ACTION_START);
            JSONObject data = new JSONObject();
            data.put("planActionId", planAction.getId());
            data.put("planActionName", planAction.getName());
            pushMqVo.setData(data);
            MqttService.pushMq(pushMqVo);
        });
        return i;
    }

    /**
     * 修改飞行行动
     *
     * @param planAction 飞行行动
     * @return 结果
     */
    @Override
    public int updatePlanAction(PlanAction planAction) {
        PlanAction planActionDB = selectPlanActionById(planAction.getId());


        if (CollectionUtil.isNotEmpty(planAction.getActionUsers())) {
            planActionUserService.deletePlanActionUserByActionId(planAction.getId());

            planAction.setPilotId(planAction.getActionUsers().stream().map(u -> u.getUserId() + "").collect(Collectors.joining(",")));
            planAction.setPilotName(planAction.getActionUsers().stream().map(PlanActionUser::getNickName).collect(Collectors.joining(",")));
            planAction.getActionUsers().forEach(u -> {
                u.setActionId(planAction.getId());
                planActionUserService.insertPlanActionUser(u);
            });
        }
        if (null != planAction.getStatus() && 2 != planAction.getStatus()) {
            List<String> pilotIdList = Arrays.asList(planAction.getPilotId().split(","));
            //根据飞手Id查询设备sn码
            List<String> droneList = userMapper.selectUserByIds(pilotIdList);
            redisCache.deleteObject(CacheConstants.PLAN_ACTION_USERNAME + planAction.getId());
            redisCache.setCacheList(CacheConstants.PLAN_ACTION_USERNAME + planAction.getId(), droneList);
            //发送mq
            droneList.stream().forEach(drone -> {
                PushMqVo pushMqVo = new PushMqVo();
                pushMqVo.setSn("");
                pushMqVo.setUserName(drone);
                pushMqVo.setType(PLAN_ACTION_MODIFY);
                JSONObject data = new JSONObject();
                data.put("planActionId", planAction.getId());
                data.put("planActionName", planAction.getName());
                pushMqVo.setData(data);
                MqttService.pushMq(pushMqVo);
            });
        }
        return planActionMapper.updatePlanAction(planAction);
    }

    /**
     * 批量删除飞行行动
     *
     * @param ids 需要删除的飞行行动主键
     * @return 结果
     */
    @Override
    public int deletePlanActionByIds(Long[] ids) throws Exception {
        //删除minio记录
        removeMinio(ids);
        return planActionMapper.deletePlanActionByIds(ids);
    }

    @Async
    public void removeMinio(Long[] ids) throws Exception {
        for (Long id : ids) {
            PlanActionRecord planActionRecord = new PlanActionRecord();
            planActionRecord.setActionId(id);
            List<PlanActionRecord> parList = planActionRecordMapper.selectPlanActionRecordList(planActionRecord);
            for (PlanActionRecord par : parList ){
                PlanActionRecordMedia planActionRecordMedia = new PlanActionRecordMedia();
                planActionRecordMedia.setRecordId(par.getId());
                List<PlanActionRecordMedia> parmList = planActionRecordMediaMapper.selectPlanActionRecordMediaList(planActionRecordMedia);
                for (PlanActionRecordMedia parm : parmList) {
                    MinioUtil.removeFile(bucketName, parm.getMediaUrl().replace(bucketName+"/",""));
                }
            }
        }
    }

    /**
     * 删除飞行行动信息
     *
     * @param id 飞行行动主键
     * @return 结果
     */
    @Override
    public int deletePlanActionById(Long id) {
        return planActionMapper.deletePlanActionById(id);
    }

    @Override
    public int bindCommand(Long id, Long userId, String username) {
        return planActionMapper.bindCommand(id, userId, username);
    }

    @Override
    public void pushMqByEndPlan(Long planId) {
        //根据id查询所有飞手及对应的sn码
//        String pilotIds = planActionMapper.selectPlanActionById(planId).getPilotId();
//        List<String> pilotIdList = Arrays.asList(pilotIds.split(","));
        //根据飞手Id查询设备sn码
//        List<String> droneList = userMapper.selectUserByIds(pilotIdList);
        List<String> droneList = redisCache.getCacheList(CacheConstants.PLAN_ACTION_USERNAME + planId);
        //发送mq
        droneList.stream().forEach(drone -> {
            PushMqVo pushMqVo = new PushMqVo();
            pushMqVo.setSn("");
            pushMqVo.setUserName(drone);
            pushMqVo.setType(PLAN_ACTION_END);
            JSONObject data = new JSONObject();
            data.put("planActionId", planId);
            data.put("planActionName", "");
            pushMqVo.setData(data);
            MqttService.pushMq(pushMqVo);
        });
        redisCache.deleteObject(CacheConstants.PLAN_ACTION_USERNAME + planId);
    }

    /***
     * 录制视频
     * @param planVideoVo
     */
    @Override
    public void recordVideo(PlanVideoVo planVideoVo) {
        //传参
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("secret", secret);
        paramMap.put("customized_path", customizedPath);
        paramMap.put("stream", planVideoVo.getActionId() + "-" + planVideoVo.getSn());
        paramMap.put("app", "live");
        paramMap.put("vhost", url);
        paramMap.put("type", 1);
        //判断是开始还是结束:0开始1结束
        if (VideoConstant.START_VIDEO == planVideoVo.getVideoState()) {
            JSONObject data = JSONObject.parseObject(HttpUtil.post(sendUrl + VideoConstant.START_RECORD, paramMap));
            if (VideoConstant.SUCCESS != data.getInteger("code")) {
                throw new ServiceException("录制失败，原因：" + data.getString("msg"));
            }
        } else {
            String data = HttpUtil.post(sendUrl + VideoConstant.STOP_RECORD, paramMap);
            System.out.println(data);
        }
    }

    @Override
    @Async
    public void insertRecordVideo(List<PlanActionRecord> planActionRecords) {
        planActionRecords.stream().forEach(planActionRecord -> {
                    /***
                     * 1、开始时间到结束时间的日期
                     * 2、获取多个文件循环上传
                     * 3、传完存记录媒体库
                     */
                    long betweenDay = DateUtil.betweenDay(planActionRecord.getFlightTimeBegin(), DateUtils.getNowDate(), true);
                    Date forDate = planActionRecord.getFlightTimeBegin();
                    for (int i = 0; i <= betweenDay; i++) {
                        DateUtil.format(forDate, "yyyy-MM-dd");
                        System.out.println(DateUtil.format(forDate, "yyyy-MM-dd"));

                        //传参
                        Map<String, Object> paramMap = new HashMap<>();
                        paramMap.put("secret", secret);
                        paramMap.put("customized_path", customizedPath);
                        paramMap.put("stream", planActionRecord.getActionId() + "-" + planActionRecord.getDroneSn());
                        paramMap.put("app", "live");
                        paramMap.put("vhost", url);
                        paramMap.put("period", DateUtil.format(forDate, "yyyy-MM-dd"));
                        paramMap.put("type", 1);
                        HttpUtil.post(sendUrl + VideoConstant.STOP_RECORD, paramMap);
                        Threads.sleep(2000);
                        JSONObject data = JSONObject.parseObject(HttpUtil.post(sendUrl + VideoConstant.GET_MP4_RECORD_FILE, paramMap));
                        if (VideoConstant.SUCCESS == data.getInteger("code")) {
                            String rootPath = data.getJSONObject("data").getString("rootPath");
                            JSONArray pathsJa = data.getJSONObject("data").getJSONArray("paths");
                            pathsJa.stream().forEach(paths -> {
                                String path = rootPath + paths;
                                try {
                                    String fileName = RuoYiConfig.getPlanAction() + "/" + planActionRecord.getActionId() + "/" + planActionRecord.getDroneSn() + "/" + Seq.getId(Seq.uploadSeqType) + paths;
                                    MinioUtil.uploadFile(bucketName, fileName, path);
                                    PlanActionRecordMedia planActionRecordMedia = new PlanActionRecordMedia();
                                    planActionRecordMedia.setMediaUrl(bucketName + fileName);
                                    planActionRecordMedia.setRecordId(planActionRecord.getId());
                                    planActionRecordMedia.setDroneSn(planActionRecord.getDroneSn());
                                    planActionRecordMedia.setMediaType(2);
                                    planActionRecordMedia.setCreateTime(DateUtils.getNowDate());
                                    planActionRecordMediaMapper.insertPlanActionRecordMedia(planActionRecordMedia);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            });
                        }
                        forDate = DateUtil.offsetDay(forDate, 1);
                    }
                }
        );
    }

    public static void main(String[] args) {


    }

}
